/* Copyright (c) 2009-2010, Sean A.O. Harney <sharney3@gmail.com> */

/* most of this file was moved out of the yacc file, so that it would be easier to C indent */

#include "omf.h"


/* prototypes */
bool _parse(void);
extern void yyrestart(FILE * input_file);
extern int yyparse();
//yacc/lex globals
extern int yylineno;
extern char *yytext;
extern FILE *yyin;

/* globals */
LLIST_P _current_func_asl;	/* used at parse-time. `current` meaning where yacc is at in the grammar */
/* for building the current function's ASL */


void yyerror(const char *errtype)
{
    char str[256];
    char *filename = glob.parser_current_filename;

    if (filename == NULL)	/* because it is parsing stdin */
	str[0] = '\0';
    else
	snprintf(str, sizeof(str), "%s:", filename);

    fprintf(stderr, "%s%d: %s near token '%s'\n", str, yylineno, errtype,
	    yytext);
    glob.parser_num_errors++;
}

bool parse_init(FILE * fp)
{
    current_func_asl_clear();
    yyin = fp;			//set yyin to the given fp
    /*
       if (fileno(yyin) != fileno(stdin)) //only prevalidate for script files
       {
       validation_mode = true;
       debug_unquiet_printf("Validating syntax...\n");
       if (_parse() == false)
       return false;
       debug_unquiet_printf("Syntactically valid program.\n");
       atexit_init();     // the time printout. TODO: move to after start perhaps.

       glob.omf_state
       ADD STATE_RESET

       if (fileno(yyin) != fileno(stdin))       //only prevalidate for script files
       {
       rewind(yyin);            // rewind input and parse again
       yyrestart(yyin);
       }
     */
    if (fileno(yyin) != fileno(stdin))
	debug_unquiet_printf
	    ("Parsing, verifying syntax and building Abstract Statement List(s)...\n");

    if (!_parse())
      {
	  fprintf(stderr,
		  "Parse failed. Syntactically invalid program.\n");
	  return false;
      }

    if (fileno(yyin) != fileno(stdin))
	debug_unquiet_printf("Syntactically valid program.\n");

    return true;
}

bool _parse(void)
{
    if (yyparse() != 0 || glob.parser_num_errors > 0)
      {
	  error_println("%d Syntax error(s).\n", glob.parser_num_errors);
	  return false;
      }
    return true;

}

void current_func_asl_clear(void)
{
    _current_func_asl = NULL;
    /* TODO: maybe in future do a shallow free'ing of some heap ptrs regarding llist */
}

/* will create list if it has not been created yet.*/
void current_func_asl_add(ASL_NODE_P stmt)
{
    /* NOTE: must append, not prepend! */
    _current_func_asl = asl_append(_current_func_asl, stmt);
}
